package ADTL;

%%

%class Lexer
%cup
%public
%type Token
%line
%scanerror LexicalError

%{
StringBuffer string = new StringBuffer();

public int getLineNumber() { return yyline + 1; }
%}

%eofval{
  return new Token(sym.EOF, getLineNumber());
%eofval}


LineTerminator = \r|\n|\r\n
InputCharacter = [^\r\n]
WhiteSpace = {LineTerminator} | [ \t\f]
/* comments */
Comment = {TraditionalComment} | {EndOfLineComment} | {DocumentationComment}
TraditionalComment = "/*" [^*] ~"*/" | "/*" "*"+ "/"
EndOfLineComment = "//" {InputCharacter}* {LineTerminator}
DocumentationComment = "/**" {CommentContent} "*"+ "/"
CommentContent = ( [^*] | \*+ [^/*] )*
Identifier = [a-zA-Z_] [a-z0-9A-Z]*
DecIntegerLiteral = 0 | [-+]?[1-9][0-9]*
IllegalInteger = [-+]?0[0-9][0-9]*
%state STRING
%%
<YYINITIAL> {
	/* comments */
	{Comment} { /* ignore */ }
	/* whitespace */
	{WhiteSpace} { /* ignore */ }
	
	"assert"          { return new Token(yytext(), sym.ASSERT, getLineNumber()); }
	"|"                { return new Token(yytext(), sym.BAR, getLineNumber()); }
	"\/"	{ return new Token(yytext(), sym.DIVIDE, getLineNumber()); }
	"{"	{ return new Token(yytext(), sym.LCBR, getLineNumber()); }
	"<="	{ return new Token(yytext(), sym.LTE, getLineNumber()); }
	"rev"	{ return new Token(yytext(), sym.REV, getLineNumber()); }
	";"	{ return new Token(yytext(), sym.SEMI, getLineNumber()); }
	"-"	{ return new Token(yytext(), sym.MINUS, getLineNumber()); }
	"!"	{ return new Token(yytext(), sym.NOT, getLineNumber()); }
	"<"	{ return new Token(yytext(), sym.LT, getLineNumber()); }
	"choose"	{ return new Token(yytext(), sym.CHOOSE, getLineNumber()); }
	"in"	{ return new Token(yytext(), sym.IN, getLineNumber()); }
	"("	 { return new Token(yytext(), sym.LP, getLineNumber()); }
	","	 { return new Token(yytext(), sym.COMMA, getLineNumber()); }
	"lock"	{ return new Token(yytext(), sym.LOCK, getLineNumber()); }
	")"	{ return new Token(yytext(), sym.RP, getLineNumber()); }
	"+"	{ return new Token(yytext(), sym.PLUS, getLineNumber()); }
	//"\"[^\"]*\"" { return new Token(yytext(), sym.QUOTE, getLineNumber()); }
	\" { string.setLength(0); yybegin(STRING); }
	"if"	{ return new Token(yytext(), sym.IF, getLineNumber()); }
	"\."	{ return new Token(yytext(), sym.DOT, getLineNumber()); }
	"}"	{ return new Token(yytext(), sym.RCBR, getLineNumber()); }
	"&&"	{ return new Token(yytext(), sym.LAND, getLineNumber()); }
	"return"	{ return new Token(yytext(), sym.RETURN, getLineNumber()); }
	"new"	{ return new Token(yytext(), sym.NEW, getLineNumber()); }
	"+="	{ return new Token(yytext(), sym.ASSIGN_PLUS, getLineNumber()); }
	"||"	{ return new Token(yytext(), sym.LOR, getLineNumber()); }
	"!="	{ return new Token(yytext(), sym.NEQ, getLineNumber()); }
	"-="	{ return new Token(yytext(), sym.ASSIGN_MINUS, getLineNumber()); }
	"="	{ return new Token(yytext(), sym.ASSIGN, getLineNumber()); }
	"=="	{ return new Token(yytext(), sym.EQ, getLineNumber()); }
	">="	{ return new Token(yytext(), sym.GTE, getLineNumber()); }
	"*"	{ return new Token(yytext(), sym.TIMES, getLineNumber()); }
	":" { return new Token(yytext(), sym.COLON, getLineNumber()); }	
	"else"	{ return new Token(yytext(), sym.ELSE, getLineNumber()); }
	"@"	{ return new Token(yytext(), sym.AT, getLineNumber()); }
	">"	{ return new Token(yytext(), sym.GT, getLineNumber()); }
	"set"	{ return new Token(yytext(), sym.SET, getLineNumber()); }
	{DecIntegerLiteral} { return new Token(yytext(), sym.INT, getLineNumber(),Integer.parseInt(yytext())); }
	{IllegalInteger} {throw new LexicalError("illegal integer format:" + yytext());}
	{Identifier} {return new Token (yytext(),sym.ID,getLineNumber(),yytext());}
}

<STRING> {
	\" 	{ ;yybegin(YYINITIAL); return new Token(yytext(),sym.QUOTE,getLineNumber(),string.toString()); }
	[^\n\r\"\\]+ {string.append( yytext() ); }
	
	\\t { string.append("\t"); }
	\\n { string.append("\n"); }
	\\r { string.append("\r"); }
	\\s { string.append(" "); }
	\\\" { string.append("\""); }
	\\\\ 	{ string.append("\\"); }
}
